package com.prj.ufdm.cloud.svr.gateway.config;

import java.lang.reflect.Method;
import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cache.interceptor.KeyGenerator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.connection.RedisPassword;
import org.springframework.data.redis.connection.RedisStandaloneConfiguration;
import org.springframework.data.redis.connection.lettuce.LettuceClientConfiguration;
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
import org.springframework.data.redis.connection.lettuce.LettucePoolingClientConfiguration;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;

import com.alibaba.fastjson.support.spring.FastJsonRedisSerializer;

@Configuration
@EnableCaching
public class RedisConfig  extends CachingConfigurerSupport  { 
	
	@Value("${main.rs.host:127.0.0.1}")
	private String mainRsHost;
    @Value("${main.rs.database:1}")
    private int mainRsDatabase;
	@Value("${main.rs.port:6379}")
	private int mainRsPort;
    @Value("${main.rs.password:}")
    private String mainRsPassword;
    
    @Value("${main.rs.maxWait:-1}")
    private int mainRsMaxWait;
    @Value("${main.rs.maxActive:10}")
    private int mainRsMaxActive;
    @Value("${main.rs.maxIdle:10}")
    private int mainRsMaxIdle;
    @Value("${main.rs.minIdle:0}")
    private int mainRsMinIdle;
    @Value("${main.rs.timeout:3000}")
    private int mainRstTimeout;
    
	@SuppressWarnings("rawtypes")
	@Bean("webPoolConfig")
	public GenericObjectPoolConfig webPoolConfig() {
	      GenericObjectPoolConfig config = new GenericObjectPoolConfig<>();
	      config.setMaxTotal(mainRsMaxActive);
	      config.setMaxIdle(mainRsMaxIdle);
	      config.setMinIdle(mainRsMinIdle);
	      config.setMaxWaitMillis(mainRsMaxWait);
	      config.setEvictorShutdownTimeoutMillis(mainRstTimeout);
	      return config;
	}

	@Bean("webRedisConfig")
	public RedisStandaloneConfiguration webRedisConfig() {
	      RedisStandaloneConfiguration config = new RedisStandaloneConfiguration();
	      config.setHostName(mainRsHost);
	      config.setPassword(RedisPassword.of("password_redis"));
	      config.setPort(6379);
	      config.setDatabase(mainRsDatabase);
	      return config;
	}
	
    @SuppressWarnings("rawtypes")
	@Bean("webFactoryConfig")
    @Primary
    public LettuceConnectionFactory webFactoryConfig(GenericObjectPoolConfig config, RedisStandaloneConfiguration redisConfig) {
        LettuceClientConfiguration clientConfiguration = LettucePoolingClientConfiguration.builder().poolConfig(config).build();
        return new LettuceConnectionFactory(redisConfig, clientConfiguration);
    }
	
    @Bean
    public CacheManager cacheManager(RedisConnectionFactory  connectionFactory) {
        return RedisCacheManager.create(connectionFactory);
    }
    
    @Bean
    public RedisSerializer<Object> fastJson2JsonRedisSerializer() {
        return new FastJsonRedisSerializer<Object>(Object.class);
    }
    
    @Bean
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory,RedisSerializer<Object> fastJson2JsonRedisSerializer) {
        RedisTemplate<String, Object> template = new RedisTemplate<String, Object>();
        template.setConnectionFactory(factory);
        
        // key采用String的序列化方式
        template.setKeySerializer(new StringRedisSerializer());
        // hash的key也采用String的序列化方式
        template.setHashKeySerializer(new StringRedisSerializer());
        
        // value序列化方式采用fastJson
        template.setValueSerializer(fastJson2JsonRedisSerializer);
        // hash的value序列化方式采用fastJson
        template.setHashValueSerializer(fastJson2JsonRedisSerializer);
        
        template.afterPropertiesSet();
        return template;
    }
    
    @Bean
    public KeyGenerator keyGenerator() {
        return new KeyGenerator() {
            @Override
            public Object generate(Object target, Method method, Object... params) {
                StringBuilder sb = new StringBuilder();
                sb.append(target.getClass().getName());
                sb.append(method.getName());
                for (Object obj : params) {
                    sb.append(obj.toString());
                }
                return sb.toString();
            }
        };
    }
}
